/**
 * 
 */
package io;

import info.Constant;
import info.Course;
import info.Group;
import info.Room;
import info.Subject;
import info.Teacher;
import infomanager.CourseManager;
import infomanager.GroupManager;
import infomanager.Helper;
import infomanager.RoomManager;
import infomanager.SubjectManager;
import infomanager.TeacherManager;

import java.util.Arrays;
import java.util.Random;

/**
 * @author vtkhanh
 * 
 */
public class Input {

    private final int HARDCODED_GROUP_CAPACITY = 30;
    private final short HARDCODED_SUBJECTS_NUM = 10;
    private final int HARDCODED_GROUPS_NUM = 10;
    private final short HARDCODED_ROOMS_NUM = 4;
    private final int HARDCODED_ROOMS_CAPACITY = 30;
    private final short HARDCODED_TEACHERS_NUM = 4;
    private final short HARDCODED_PERIODS_NUM = 3;

    public void setHardcodedInput() {
	setHardcodedGroups();
	setHardcodedTeachers();
	setHardcodedSubjects();
	setHardcodedRooms();
	setHardcodedCourses();
    }

    /***************************** COURSE *******************************/
    public void setHardcodedCourses() {
	Group[] groups = GroupManager.getGroups();
	int subjectId;
	int coursesNum = HARDCODED_GROUPS_NUM * HARDCODED_PERIODS_NUM;
	Course[] courses = new Course[coursesNum];
	Subject[] subjects = SubjectManager.getSubjects();
	int courseId = 0;

	for (short i = 0; i < HARDCODED_GROUPS_NUM; i++) {
	    subjectId = groups[i].getSubjectId();
	    for (short period = 0; period < subjects[subjectId]
		    .getPeriodCount(); period++) {
		Teacher teacher = getHardcodedTeacherForSubject(subjectId);
		courses[courseId] = new Course(teacher, groups[i],
			subjects[subjectId], period);
		courseId++;
	    }
	}

	CourseManager.setCourses(courses);
    }

    public static void setCourses() {
	Group[] groups = GroupManager.getGroups();
	Subject[] subjects = SubjectManager.getSubjects();	
	int subjectId;
	int coursesNum = 0;
	
	for (Group group : groups) {
	    Subject subject = subjects[group.getSubjectId()];
	    int periods = subject.getPeriodCount();
	    coursesNum += periods;
	}
	
	Course[] courses = new Course[coursesNum];
	int courseIndex = 0;
	for (int i = 0; i < GroupManager.getNumberOfGroups(); i++) {	    
	    subjectId = groups[i].getSubjectId();
	    Subject subject = SubjectManager.getSubjectById(subjectId);
	    for (int period = 0; period < subject.getPeriodCount(); period++) {
		Teacher teacher = getTeacherForSubject(subject);
		courses[courseIndex] = new Course(teacher, groups[i], subject, period);
		courseIndex++;
	    }
	}
    }
        

    /***************************** HELPERS *******************************/
    private Teacher getHardcodedTeacherForSubject(int subjectId) {
	int teacherId;
	short[] subjectIds;
	Teacher[] teachers = TeacherManager.getTeachers();
	Teacher result = null;
	do {
	    teacherId = getRandomIndex(HARDCODED_TEACHERS_NUM);
	    subjectIds = teachers[teacherId].getSubjectIds();
	    for (short id : subjectIds) {
		if (id == subjectId) {
		    result = teachers[teacherId];
		    break;
		}
	    }
	} while (result == null);
	
	return result;
    }
        
    private static Teacher getTeacherForSubject(Subject subject) {	
	int[] teacherIds = subject.getTeacherIds();
	int chosenId;
	Teacher result = null;
	do {
	    chosenId = getRandomIndex(TeacherManager.getNumberOfTeachers());
	    for (int id : teacherIds) {
		if (id == chosenId) {
		    result = TeacherManager.getTeacherById(chosenId);
		    break;
		}
	    }	    
	} while (result == null);
	
	return result;
    }

    private static int getRandomIndex(int range) {
	Random random = new Random();
	int randomIndex = random.nextInt(range);
	return randomIndex;
    }

    /***************************** SUBJECT *******************************/
    public void setHardcodedSubjects() {
	Subject[] subjects = new Subject[HARDCODED_SUBJECTS_NUM];
	int[] teacherIds = new int[HARDCODED_TEACHERS_NUM];
	
	for (int i = 0; i < HARDCODED_TEACHERS_NUM; i++) {
	    teacherIds[i] = i;
	}

	for (short i = 0; i < HARDCODED_SUBJECTS_NUM; i++) {
	    subjects[i] = new Subject(i, (short) HARDCODED_PERIODS_NUM, teacherIds);
	}

	SubjectManager.setSubjects(subjects);
    }

    public static void addSubject(int subjectId, int periods, int[] teacherIds) {
	Subject subject = new Subject((short) subjectId, (short) periods, teacherIds);
	SubjectManager.addSubject(subject);
	
	// test
	System.out.println("subject-id = " + subjectId + " periods = " + periods + " teachers = " + teacherIds);
    }

    public static void setNumberOfSubjects(int num) {
	System.out.println("num = " + num);
	//SubjectManager.setNumberOfSubjects(num);
    }

    /***************************** TEACHER *******************************/
    public void setHardcodedTeachers() {
	Teacher[] teachers = new Teacher[HARDCODED_TEACHERS_NUM];
	short[] subjects = new short[HARDCODED_SUBJECTS_NUM];

	for (short i = 0; i < HARDCODED_SUBJECTS_NUM; i++) {
	    subjects[i] = i;
	}

	for (short i = 0; i < HARDCODED_TEACHERS_NUM; i++) {
	    boolean[] timeslots = new boolean[Constant.TIMESLOT_NUM];
	    Arrays.fill(timeslots, true);
	    teachers[i] = new Teacher(i, subjects, timeslots);
	}

	TeacherManager.setTeachers(teachers);
    }

    public static void addTeacher(short teacherId, short[] subjectIds) {
	boolean[] timeslots = new boolean[Constant.TIMESLOT_NUM];
	Arrays.fill(timeslots, true);
	Teacher teacher = new Teacher(teacherId, subjectIds, timeslots);
	TeacherManager.addTeacher(teacher);
    }

    public static void setNumberOfTeacher(int num) {
	TeacherManager.setNumberOfTeachers(num);
    }

    /***************************** GROUP *******************************/
    public void setHardcodedGroups() {
	Group[] groups = new Group[HARDCODED_GROUPS_NUM];

	for (short i = 0; i < HARDCODED_GROUPS_NUM; i++) {
	    boolean[] timeslots = new boolean[Constant.TIMESLOT_NUM];
	    Arrays.fill(timeslots, true);
	    groups[i] = new Group(i, Helper.getRadom(HARDCODED_SUBJECTS_NUM),
		    timeslots, HARDCODED_GROUP_CAPACITY);
	}

	GroupManager.setGroups(groups);
    }

    public static void addGroup(int groupId, int subjectId, int capacity) {
	boolean[] timeslots = new boolean[Constant.TIMESLOT_NUM];
	Arrays.fill(timeslots, true);
	Group group = new Group(groupId, subjectId, timeslots, capacity);
	GroupManager.addGroup(group);
    }

    public static void setNumberOfGroups(int num) {
	GroupManager.setNumberOfGroups(num);
    }

    /***************************** ROOM *******************************/
    public void setHardcodedRooms() {
	Room[] rooms = new Room[HARDCODED_ROOMS_NUM];

	for (short i = 0; i < HARDCODED_ROOMS_NUM; i++) {
	    boolean[] timeslots = new boolean[Constant.TIMESLOT_NUM];
	    Arrays.fill(timeslots, true);
	    rooms[i] = new Room(i, HARDCODED_ROOMS_CAPACITY, timeslots);
	}

	RoomManager.setRooms(rooms);
    }

    public static void addRoom(int roomId, int capacity) {
	boolean[] timeslots = new boolean[Constant.TIMESLOT_NUM];
	Arrays.fill(timeslots, true);
	Room room = new Room((short) roomId, capacity, timeslots);
	RoomManager.addRoom(room);
    }

    public static void setNumberOfRooms(int num) {
	RoomManager.setNumberOfRooms(num);
    }

}
